//------------------------------------------------------------------------------
// <copyright file="RpcSocketChannel.h" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

#pragma once

#include "IRpcChannel.h"
#include "IRpcStringSocket.h"

namespace Microsoft { namespace Internal { namespace GamesTest { namespace Rpc { namespace Server { namespace Ut
{
	class RpcSocketChannelTests;
}}}}}}

namespace Microsoft { namespace Internal { namespace GamesTest { namespace Rpc { namespace Server
{
	/// <summary>
	/// A socket-specific implementation of the IRpcChannel interface.
	/// This is used for sending responses from the server back to the client along a socket.
	/// </summary>
	class RpcSocketChannel : public IRpcChannel, public std::enable_shared_from_this<RpcSocketChannel>
	{
	private:
		friend class Microsoft::Internal::GamesTest::Rpc::Server::Ut::RpcSocketChannelTests;

		IRpcStringSocket* m_socket;
		RequestReceivedCallback m_requestReceivedCallback;
		ChannelDisconnectedCallback m_channelDisconnectedCallback;

	public:
		/// <summary>
		/// Initializes a new instance of the RpcSocketChannel class.
		/// </summary>
		/// <param name="socket">A wrapper around the actual socket that is connected to the client.  This parameter is a weak_ptr so that if the client
		/// disconnects while a request is being processed, then this object won't keep the client object alive any longer than it needs to.</param>
		RpcSocketChannel(IRpcStringSocket* socket);

		/// <summary>
		/// Sends a message from the server to the client.
		/// </summary>
		/// <param name="message">The message to be sent to the client.</param>
		/// <param name="serverId">The Id of the RpcServer sending the message.</param>
		/// <param name="errorCode">The error code for any errors that were encountered while trying to process the request.</param>
		virtual GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SendRpcMessage(const std::wstring& message, const GUID& serverId, HRESULT errorCode = S_OK);

		/// <summary>
		/// Indicates that the channel shall start listening for incoming requests and pass them along to the specified request handler.
		/// </summary>
		/// <param name="requestReceived">A function to be invoked when a request is received.</param>
		/// <param name="channelDisconnected">A function to be invoked when the channel has disconnected.</param>
		virtual GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT StartListening(RequestReceivedCallback requestReceived, ChannelDisconnectedCallback channelDisconnected);

		virtual ~RpcSocketChannel();
	private:
		void OnStringReceived(IRpcStringSocket* socket, std::wstring data);
		void OnSocketDisconnected(IRpcStringSocket* socket);
	};

}}}}}